package com.ruoyi.framework.aspectj;

import java.lang.reflect.Method;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.UserDataIsolation;
import org.aspectj.lang.reflect.MethodSignature;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysDeptService;

import javax.servlet.http.HttpServletRequest;

/**
 * 用户数据隔离
 * @author yetao
 *
 */
@Aspect
@Component
@Slf4j
public class UserDataIsolationAspect {
	
	@Autowired
	private ISysDeptService deptService;
	
	/**
     * 用户数据隔离过滤关键字
     */
    public static final String USER_DATA_ISOLATION = "userDataIsolation";

	// 配置织入点
    @Pointcut("@annotation(com.ruoyi.common.annotation.UserDataIsolation)")
    public void userDataIsolationPointCut()
    {
    }

    @Before("userDataIsolationPointCut()")
    public void doBefore(JoinPoint point) throws Throwable
    {
        clearUserDataIsolation(point);
        handleUserDataIsolation(point);
    }
    
    protected void handleUserDataIsolation(final JoinPoint joinPoint)
    {
        // 获得注解
        UserDataIsolation controllerUserDataIsolation = getAnnotationLog(joinPoint);
        if (controllerUserDataIsolation == null)
        {
            return;
        }
        LoginUser loginUser = null;
        HttpServletRequest request = null;
        try {
            request = ServletUtils.getRequest();
        } catch (Exception e) {}
        if (request != null) {
            loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(request);
        }
        // 获取当前的用户
        if (StringUtils.isNotNull(loginUser))
        {
            SysUser currentUser = loginUser.getUser();
            // 如果是超级管理员，则不过滤数据
            // 如果不是管理员，则根据用户的所属部门查询到公司，再根据所属公司进行数据隔离
            if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
            {
            	SysDept userDept = currentUser.getDept();
                userDataIsolationFilter(joinPoint, currentUser,controllerUserDataIsolation.tableAlias(), userDept);
            }
        }
    }

    /**
     * 数据范围过滤
     *
     * @param joinPoint 切点
     * @param user 用户
     * @param userAlias 别名
     */
    public static void userDataIsolationFilter(JoinPoint joinPoint, SysUser user, String tableAlias, SysDept userDept)
    {
        StringBuilder sqlString = new StringBuilder();

        long companyId = userDept.getParentId()==0L ? 
        		userDept.getDeptId().longValue():
        		Long.parseLong(userDept.getAncestors().split(",")[1]);
        		
        if(tableAlias==null || "".equals(tableAlias)) {
            sqlString.append(StringUtils.format(" AND (company_id = {} )", companyId));
        } else {
            sqlString.append(StringUtils.format(" AND ({}.company_id = {} )", tableAlias, companyId));
        }

        if (StringUtils.isNotBlank(sqlString.toString()))
        {
            Object params = joinPoint.getArgs()[0];
            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
            {
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(USER_DATA_ISOLATION, sqlString.toString());
            }
        }
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private UserDataIsolation getAnnotationLog(JoinPoint joinPoint)
    {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null)
        {
            return method.getAnnotation(UserDataIsolation.class);
        }
        return null;
    }

    /**
     * 拼接权限sql前先清空params.userDataIsolation参数防止注入
     */
    private void clearUserDataIsolation(final JoinPoint joinPoint)
    {
    	Object params = joinPoint.getArgs()[0];
        if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
        {
        	BaseEntity baseEntity = (BaseEntity) params;
        	baseEntity.getParams().put(USER_DATA_ISOLATION, "");
        }
    }
}
